package com.asiainfo.dacp.datastash.broker.facade.service;

import com.asiainfo.dacp.datastash.broker.core.BrokerContext;
import com.asiainfo.dacp.datastash.broker.core.StashUnitModel;
import com.asiainfo.dacp.datastash.broker.core.enums.UnitStateEnum;
import com.asiainfo.dacp.datastash.broker.core.vo.StashUnit;
import com.asiainfo.dacp.datastash.broker.core.vo.StashUnitDefine;
import com.asiainfo.dacp.datastash.broker.tracelog.StashTraceLogVo;
import com.asiainfo.dacp.datastash.broker.tracelog.StashTraceLogger;
import com.asiainfo.dacp.datastash.domain.unit.models.DataStashUnit;
import com.asiainfo.dacp.datastash.domain.unit.repos.DataStashUnitRepository;
import com.asiainfo.dacp.metamodel.domain.ds.model.MetaDataSource;
import com.asiainfo.dacp.metamodel.domain.ds.repo.MetaDataSourceRepository;
import com.asiainfo.dacp.util.BeanConvertUtils;

import org.apache.curator.shaded.com.google.common.base.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 实现unit配置数据的初始加载
 * 1.更新stash_unit表中的到每个broker vm级的中
 * 2.更新需要处理的单元+批次，放入unit_status_list
 * 3.刷新增强队列unit_wait_queue
 *
 * @author MeiKefu
 * @date 2017-11-8
 */
@Service
public class UnitInitService {

    @Autowired
    private DataStashUnitRepository dataStashUnitRepository;

    @Autowired
    private MetaDataSourceRepository metaDataSourceRepository;

	@Autowired
	private StashTraceLogger tracelog;
    private String clzName = this.getClass().getSimpleName();

    /**
     * 更新自己VM的信息
     */
    public void initUnit(){
        tracelog.info(new StashTraceLogVo(clzName,"initUnit:start","加载数据库配置"));
        //TODO 1.从数据库中加载，需要完成与BrokerContext中VM级的参数对比，如果是任务在运行中，禁止更新
    	List<DataStashUnit> dataStashUnitList = dataStashUnitRepository.findAll();

    	if(dataStashUnitList!=null && dataStashUnitList.size()>0){
    		for(DataStashUnit dataStashUnit : dataStashUnitList){
				if("1".equals(dataStashUnit.getState())){
					StashUnitDefine unit = BeanConvertUtils.copyBean(dataStashUnit,StashUnitDefine.class);
                    unit.transformUnitSched(dataStashUnit.getUnitSteps());
                    BrokerContext.getInstance().getStashUnitDefs().put(unit.getUnitCode(),unit);
				}
			}

			if(BrokerContext.getInstance().getStashUnitDefs().size()>0){
                tracelog.info(new StashTraceLogVo(clzName,"loadVMUnit","unit_list加载成功"));
            }else{
                tracelog.warn(new StashTraceLogVo(clzName,"loadVMUnit:fail","unit_list加载为空，是否没有在用的状态"));
            }
		}else{
            tracelog.error(new StashTraceLogVo(clzName,"load:none","数据库dacp_datastash_unit配置单元为空"));
		}

        try {
            List<MetaDataSource> dataSources = metaDataSourceRepository.findAll();

            if(dataSources!=null && dataSources.size()>0 ){
                for(MetaDataSource dataSource:dataSources){
                    BrokerContext.getInstance().getDsDefs().put(dataSource.getName(),dataSource);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Autowired
    private StashUnitModel stashUnitModel;

    public void updateUnitBatchNo(StashUnitDefine memUnit){
    	try {
			DataStashUnit dbUnit = dataStashUnitRepository.findByCode(memUnit.getUnitCode());
			stashUnitModel.updateUnitBatchNo(memUnit.getUnitCode(),dbUnit.getBatchNo());
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    
    /**
     * 更新共享内存的当前最新批次
     */
    public void updateUnitBatchNo(){

        List<DataStashUnit> dbUnits = dataStashUnitRepository.findAll();

        if(dbUnits==null || dbUnits.size()==0){
            tracelog.error(new StashTraceLogVo(clzName,"updateUnitBatchNo:error","加载数据库单元配置失败"));
        }
 
        /**
         * 更新内存批次, 以数据库批次为准
         * 
         */
        for(DataStashUnit dbUnit : dbUnits) {

            String redisBatchNo = stashUnitModel.getCurrentUnitBatchNo(dbUnit.getUnitCode());
            String dbBatchNo = dbUnit.getBatchNo();
            if(Strings.isNullOrEmpty(redisBatchNo) || !redisBatchNo.equals(dbBatchNo)){
                //共享内存的当前批次为空时，新增当前的批次
            	/**
            	 * TODO 前提： 数据库批次不为空
            	 * 
            	 * */
            	stashUnitModel.updateUnitBatchNo(dbUnit.getUnitCode(), dbBatchNo);
            }
        }
    }

    /**
     * 更新共享内存的等待队列，必须主节点做
     */
    public void updateWaitQueue(){
        //刷新单元桶，需要锁定获取任务的操作，等待单元桶刷新完毕才能开启
        //1.锁定单元桶
        //stashUnitModel.lockUnitWaitQueue();
    	
    	
    	//更新state表和redis缓存，目前以redis缓存驱动
    	

        //2.更新整个队列
        List<StashUnit> stashUnitList = stashUnitModel.getStashUnitList();

        if(stashUnitList==null){
            tracelog.warn(new StashTraceLogVo(clzName,"unitWaitUpdate:warn","unit_status_list没有的内容"));
        }

        //TODO 需要优先级排序
        List<String> tmpList = new ArrayList<>();
        
        for (StashUnit stashUnit : stashUnitList){
        	//TODO 需避免重复－ 在datastash:unit_list 中增加字段标识已经开始处理
        	if(stashUnit.isInit()){
        		stashUnit.setState(UnitStateEnum.BLOCKED_RELAY.value());
        		stashUnitModel.updateUnit(stashUnit);
        		
                tmpList.add(stashUnit.getUnitProcId());
            }
        }

        if(tmpList.size() > 0){
        	stashUnitModel.updateWaitQueue(tmpList);
            tracelog.info(new StashTraceLogVo(clzName,"unitUpdate:complete","更新unit_wait_queue成功：更新数："+tmpList.size()));
        }

        //3.解锁单元桶
        //stashUnitModel.unlockUnitWaitQueue();
	}

}
